﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections;
using System.Collections.Generic;
using Emulator.Base;
using Emulator.GameBoy;
using Emulator.GameBoy.CPU;
using Emulator.GameBoy.CPU.Instructions;
using Emulator.GameBoyConfig;
using Emulator.GameBoy.Memory;

namespace GameboyCPUALUTest
{
    [TestClass]
    public class InstructionTestClass
    {
        GameBoyMemory mMemory = new GameBoyMemory();
        GameBoyCPU mCPU ;

        public InstructionTestClass()
        {
            mCPU = new GameBoyCPU(mMemory);
            mCPU.ResetCPU();
        }

        [TestMethod]
        public void TestADC()
        {
            mCPU.CFlag = false;
            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformADCOperation(mCPU, 0xFF);
            Assert.IsTrue(mCPU.CFlag, "CFlag=false 0xFF 0xFF CFlag result");
            Assert.IsTrue(mCPU.HFlag, "CFlag=false 0xFF 0xFF HFlag result");
            Assert.IsFalse(mCPU.ZFlag, "CFlag=false 0xFF 0xFF ZFlag result");
            Assert.IsFalse(mCPU.NFlag, "CFlag=false 0xFF 0xFF NFlag result");
            Assert.AreEqual(0xFE, mCPU.ReadRegister8(GBCPURegister.A), "CFlag=false 0xFF 0xFF Result");

            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformADCOperation(mCPU, 0xFF);
            Assert.IsTrue(mCPU.CFlag, "CFlag=true 0xFF 0xFF CFlag result");
            Assert.IsTrue(mCPU.HFlag, "CFlag=true 0xFF 0xFF HFlag result");
            Assert.IsFalse(mCPU.ZFlag, "CFlag=true 0xFF 0xFF ZFlag result");
            Assert.IsFalse(mCPU.NFlag, "CFlag=true 0xFF 0xFF NFlag result");
            Assert.AreEqual(0xFF, mCPU.ReadRegister8(GBCPURegister.A), "CFlag=true 0xFF 0xFF result");

            mCPU.CFlag = false;
            mCPU.WriteRegister8(GBCPURegister.A, 0);
            GameBoyInstruction.PerformADCOperation(mCPU, 0);
            Assert.IsFalse(mCPU.CFlag, "CFlag=false 0 0 CFlag result");
            Assert.IsFalse(mCPU.HFlag, "CFlag=false 0 0 HFlag result");
            Assert.IsTrue(mCPU.ZFlag, "CFlag=false 0 0 ZFlag result");
            Assert.IsFalse(mCPU.NFlag, "CFlag=false 0 0 NFlag result");
            Assert.AreEqual(0x0, mCPU.ReadRegister8(GBCPURegister.A), "CFlag=false 0x0 0x0 Result");

            mCPU.CFlag = true;
            mCPU.WriteRegister8(GBCPURegister.A, 0x0);
            GameBoyInstruction.PerformADCOperation(mCPU, 0x0);
            Assert.IsFalse(mCPU.CFlag, "CFlag=true 0x0 0x0 CFlag result");
            Assert.IsFalse(mCPU.HFlag, "CFlag=true 0 0 HFlag result");
            Assert.IsFalse(mCPU.ZFlag, "CFlag=true 0 0 ZFlag result");
            Assert.IsFalse(mCPU.NFlag, "CFlag=true 0 0 NFlag result");
            Assert.AreEqual(0x1, mCPU.ReadRegister8(GBCPURegister.A), "CFlag=false 0x0 0x0 Result");

            mCPU.CFlag = true;
            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformADCOperation(mCPU, 0x0);
            Assert.IsTrue(mCPU.CFlag, "CFlag=true 0xFF 0x0 CFlag result");
            Assert.IsTrue(mCPU.HFlag, "CFlag=true 0xFF 0 HFlag result");
            Assert.IsFalse(mCPU.ZFlag, "CFlag=true 0xFF 0 ZFlag result");
            Assert.IsFalse(mCPU.NFlag, "CFlag=true 0xFF 0 NFlag result");
            Assert.AreEqual(0x0, mCPU.ReadRegister8(GBCPURegister.A), "CFlag=false 0xFF 0x0 Result");

            mCPU.CFlag = false;
            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformADCOperation(mCPU, 0x0);
            Assert.IsFalse(mCPU.CFlag, "CFlag=false 0xFF 0x0 CFlag result");
            Assert.IsFalse(mCPU.HFlag, "CFlag=false 0xFF 0 HFlag result");
            Assert.IsFalse(mCPU.ZFlag, "CFlag=false 0xFF 0 ZFlag result");
            Assert.IsFalse(mCPU.NFlag, "CFlag=false 0xFF 0 NFlag result");
            Assert.AreEqual(0xFF, mCPU.ReadRegister8(GBCPURegister.A), "CFlag=false 0xFF 0x0 Result");

        }

        [TestMethod]
        public void TestADD16()
        {
            mCPU.ZFlag = true;
            mCPU.WriteRegister8(GBCPURegister.H, 0xFF);
            mCPU.WriteRegister8(GBCPURegister.L, 0xFF);
            GameBoyInstruction.PerformADD16Operation(mCPU, 0xFFFF);
            Assert.IsFalse(mCPU.NFlag, "0xFFFF+0xFFFF:NFlag test");
            Assert.IsTrue(mCPU.CFlag, "0xFFFF+0xFFFF:Carry Flag test");
            Assert.IsTrue(mCPU.HFlag, "0xFFFF+0xFFFF:Half Flag test");
            Assert.IsFalse(mCPU.ZFlag, "0xFFFF+0xFFFF:ZFlag test");
            Assert.AreEqual(0xFFFE, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0xFFFF+0xFFFF:Result Compare test");

            mCPU.ZFlag = false;
            mCPU.WriteRegister8(GBCPURegister.H, 0);
            mCPU.WriteRegister8(GBCPURegister.L, 0);
            GameBoyInstruction.PerformADD16Operation(mCPU, 0);
            Assert.IsFalse(mCPU.NFlag, "0+0:NFlag test");
            Assert.IsFalse(mCPU.CFlag, "0+0:Carry Flag test");
            Assert.IsFalse(mCPU.HFlag, "0+0:Half Flag test");
            Assert.IsTrue(mCPU.ZFlag, "0+0:ZFlag test");
            Assert.AreEqual(0, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0+0:Result Compare test");

            mCPU.ZFlag = false;
            mCPU.WriteRegister8(GBCPURegister.H, 0xFF);
            mCPU.WriteRegister8(GBCPURegister.L, 0xFF);
            GameBoyInstruction.PerformADD16Operation(mCPU, 1);
            Assert.IsFalse(mCPU.NFlag, "0xFFFF+1:NFlag test");
            Assert.IsTrue(mCPU.CFlag, "0xFFFF+1:Carry Flag test");
            Assert.IsTrue(mCPU.HFlag, "0xFFFF+1:Half Flag test");
            Assert.IsTrue(mCPU.ZFlag, "0xFFFF+1:ZFlag test");
            Assert.AreEqual(0, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0xFFFF+1:Result Compare test");

            mCPU.ZFlag = false;
            mCPU.WriteRegister8(GBCPURegister.H, 0);
            mCPU.WriteRegister8(GBCPURegister.L, 0xFF);
            GameBoyInstruction.PerformADD16Operation(mCPU,1);
            Assert.IsFalse(mCPU.NFlag, "0xFF+1:NFlag test");
            Assert.IsFalse(mCPU.CFlag, "0xFF+1:Carry Flag test");
            Assert.IsTrue(mCPU.HFlag, "0xFF+1:Half Flag test");
            Assert.IsFalse(mCPU.ZFlag, "0xFF+1:ZFlag test");
            Assert.AreEqual(0x100, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0xFF+1:Result Compare test");

            mCPU.ZFlag = false;
            mCPU.WriteRegister8(GBCPURegister.H, 0xFF);
            mCPU.WriteRegister8(GBCPURegister.L, 0);
            GameBoyInstruction.PerformADD16Operation(mCPU, 1);
            Assert.IsFalse(mCPU.NFlag, "0xFF00+1:NFlag test");
            Assert.IsFalse(mCPU.CFlag, "0xFF00+1:Carry Flag test");
            Assert.IsFalse(mCPU.HFlag, "0xFF00+1:Half Flag test");
            Assert.IsFalse(mCPU.ZFlag, "0xFF00+1:ZFlag test");
            Assert.AreEqual(0xFF01, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0xFF00+1:Result Compare test");

            mCPU.ZFlag = false;
            mCPU.WriteRegister8(GBCPURegister.H, 0xFF);
            mCPU.WriteRegister8(GBCPURegister.L, 0);
            GameBoyInstruction.PerformADD16Operation(mCPU, 1);
            Assert.IsFalse(mCPU.NFlag, "0xFF00+1:NFlag test");
            Assert.IsFalse(mCPU.CFlag, "0xFF00+1:Carry Flag test");
            Assert.IsFalse(mCPU.HFlag, "0xFF00+1:Half Flag test");
            Assert.IsFalse(mCPU.ZFlag, "0xFF00+1:ZFlag test");
            Assert.AreEqual(0xFF01, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0xFF00+1:Result Compare test");

            mCPU.ZFlag = false;
            mCPU.WriteRegister8(GBCPURegister.H, 0xFF);
            mCPU.WriteRegister8(GBCPURegister.L, 0);
            GameBoyInstruction.PerformADD16Operation(mCPU, 0x100);
            Assert.IsFalse(mCPU.NFlag, "0xFF00+0x100:NFlag test");
            Assert.IsTrue(mCPU.CFlag, "0xFF00+0x100:Carry Flag test");
            Assert.IsFalse(mCPU.HFlag, "0xFF00+0x100:Half Flag test");
            Assert.IsTrue(mCPU.ZFlag, "0xFF00+0x100:ZFlag test");
            Assert.AreEqual(0, (mCPU.ReadRegister8(GBCPURegister.H) << 8) + mCPU.ReadRegister8(GBCPURegister.L), "0xFF00+0x100:Result Compare test");
        }

        [TestMethod]
        public void TestAND()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0xF);
            GameBoyInstruction.PerformAND8Operation(mCPU, 0x0);
            Assert.IsTrue(mCPU.ZFlag, "0xF and 0x0:Zero Flag test");
            Assert.IsFalse(mCPU.NFlag, "0xF and 0x0:Zero Nlag test");
            Assert.IsTrue(mCPU.HFlag, "0xF and 0x0:Zero Hlag test");
            Assert.IsFalse(mCPU.CFlag, "0xF and 0x0:Zero Clag test");
            Assert.AreEqual(0, mCPU.ReadRegister8(GBCPURegister.A), "0xF and 0:Result Compare test");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF);
            GameBoyInstruction.PerformAND8Operation(mCPU, 0xF0);
            Assert.IsTrue(mCPU.ZFlag, "0xF and 0xF0:Zero Flag test");
            Assert.IsFalse(mCPU.NFlag, "0xF and 0xF0:Zero Nlag test");
            Assert.IsTrue(mCPU.HFlag, "0xF and 0xF0:Zero Hlag test");
            Assert.IsFalse(mCPU.CFlag, "0xF and 0xF0:Zero Clag test");
            Assert.AreEqual(0, mCPU.ReadRegister8(GBCPURegister.A), "0xF and 0xF0:Result Compare test");

            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformAND8Operation(mCPU, 0xF);
            Assert.IsFalse(mCPU.ZFlag, "0xFF and 0xF:Zero Flag test");
            Assert.IsFalse(mCPU.NFlag, "0xFF and 0xF:Zero Nlag test");
            Assert.IsTrue(mCPU.HFlag, "0xFF and 0xF:Zero Hlag test");
            Assert.IsFalse(mCPU.CFlag, "0xFF and 0xF:Zero Clag test");
            Assert.AreEqual(0xF, mCPU.ReadRegister8(GBCPURegister.A), "0xFF and 0xF:Result Compare test");
        }

        [TestMethod]
        public void TestBIT()
        {
            
            GameBoyInstruction.PerformBITOperation(mCPU,0, 0xF);
            Assert.IsFalse(mCPU.ZFlag, "0,0xF bit:Zero Flag test");

            GameBoyInstruction.PerformBITOperation(mCPU, 1, 0xF);
            Assert.IsFalse(mCPU.ZFlag, "1,0xF bit:Zero Flag test");

            GameBoyInstruction.PerformBITOperation(mCPU, 7, 0xF);
            Assert.IsTrue(mCPU.ZFlag, "1,0xF bit:Zero Flag test");

            GameBoyInstruction.PerformBITOperation(mCPU, 7, 0xF0);
            Assert.IsFalse(mCPU.ZFlag, "7,0xF0 bit:Zero Flag test");

            GameBoyInstruction.PerformBITOperation(mCPU, 1, 0xF0);
            Assert.IsTrue(mCPU.ZFlag, "1,0xF0 bit:Zero Flag test");

            GameBoyInstruction.PerformBITOperation(mCPU, 4, 0xF0);
            Assert.IsFalse(mCPU.ZFlag, "4,0xF0 bit:Zero Flag test");
        }

        [TestMethod]
        public void TestCALL()
        {
            int mCurrentSP = mCPU.StackPointer;
            mCPU.ProgramCounter = 0xFF00;

            GameBoyInstruction.PerformCALLOperation(mCPU, true, 0xFF);
            Assert.AreEqual(mCurrentSP - 2, mCPU.StackPointer, "SP test");
            Assert.AreEqual(0x0, mCPU.PopStack(), "low address test");
            Assert.AreEqual(0xff, mCPU.PopStack(), "high address test");
            Assert.AreEqual(0xff, mCPU.ProgramCounter, "address test");

            GameBoyInstruction.PerformCALLOperation(mCPU, true, 0xFFFF);
            Assert.AreEqual(0xFFFF, mCPU.ProgramCounter, "address test");

        }

        [TestMethod]
        public void TestCP()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformCPOperation(mCPU, 0xF);
            Assert.IsFalse(mCPU.ZFlag, "0xFF 0xF z flag");
            Assert.IsTrue(mCPU.NFlag, "0xFF 0xF n flag");
            Assert.IsFalse(mCPU.HFlag, "0xFF 0xF h flag");
            Assert.IsFalse(mCPU.CFlag, "0xFF 0xF c flag");

            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformCPOperation(mCPU, 0xFF);
            Assert.IsTrue(mCPU.ZFlag, "0xFF 0xFF z flag");
            Assert.IsTrue(mCPU.NFlag, "0xFF 0xFF n flag");
            Assert.IsFalse(mCPU.HFlag, "0xFF 0xFF h flag");
            Assert.IsFalse(mCPU.CFlag, "0xFF 0xFF c flag");

            mCPU.WriteRegister8(GBCPURegister.A, 0x0);
            GameBoyInstruction.PerformCPOperation(mCPU, 0xFF);
            Assert.IsFalse(mCPU.ZFlag, "0 0xFF z flag");
            Assert.IsTrue(mCPU.NFlag, "0 0xFF n flag");
            Assert.IsTrue(mCPU.HFlag, "0 0xFF h flag");
            Assert.IsTrue(mCPU.CFlag, "0 0xFF c flag");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            GameBoyInstruction.PerformCPOperation(mCPU, 0xF);
            Assert.IsFalse(mCPU.ZFlag, "0xF0 0xF z flag");
            Assert.IsTrue(mCPU.NFlag, "0xF0 0xF n flag");
            Assert.IsTrue(mCPU.HFlag, "0xF0 0xF h flag");
            Assert.IsFalse(mCPU.CFlag, "0xF0 0xF c flag");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF);
            GameBoyInstruction.PerformCPOperation(mCPU, 0xF0);
            Assert.IsFalse(mCPU.ZFlag, "0xF 0xF0 z flag");
            Assert.IsTrue(mCPU.NFlag, "0xF 0xF0 n flag");
            Assert.IsFalse(mCPU.HFlag, "0xF 0xF0 h flag");
            Assert.IsTrue(mCPU.CFlag, "0xF 0xF0 c flag");
        }

        [TestMethod]
        public void TestCPL()
        {
            CPL2FInstruction instruction = new CPL2FInstruction();
            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            instruction.PerformOperation(mCPU, mMemory);
            Assert.IsTrue(mCPU.HFlag, "0xF0 h flag");
            Assert.IsTrue(mCPU.NFlag, "0xF0 n flag");
            Assert.AreEqual(0xF, mCPU.ReadRegister8(GBCPURegister.A));

            mCPU.WriteRegister8(GBCPURegister.A, 0xF);
            instruction.PerformOperation(mCPU, mMemory);
            Assert.IsTrue(mCPU.HFlag, "0xF h flag");
            Assert.IsTrue(mCPU.NFlag, "0xF n flag");
            Assert.AreEqual(0xF0, mCPU.ReadRegister8(GBCPURegister.A));
        }

        [TestMethod]
        public void TestDAA()
        {
            DAA27Instruction instruction = new DAA27Instruction();
            mCPU.WriteRegister8(GBCPURegister.A, 0x22);
            GameBoyInstruction.PerformADDOperation(mCPU, 0x39);
            instruction.PerformOperation(mCPU, mMemory);
            Assert.AreEqual(0x61, mCPU.ReadRegister8(GBCPURegister.A), "0x22 0x5B");

            mCPU.WriteRegister8(GBCPURegister.A, 0x91);
            GameBoyInstruction.PerformADDOperation(mCPU, 0x92);
            instruction.PerformOperation(mCPU, mMemory);
            Assert.AreEqual(0x83, mCPU.ReadRegister8(GBCPURegister.A), "0x91 0x92");
            Assert.IsTrue(mCPU.CFlag, "0x91 0x92 CFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0x99);
            GameBoyInstruction.PerformSUB8Operation(mCPU, 0x11);
            instruction.PerformOperation(mCPU, mMemory);
            Assert.AreEqual(0x88, mCPU.ReadRegister8(GBCPURegister.A), "0x99 sub 0x11");

            mCPU.WriteRegister8(GBCPURegister.A, 0x19);
            GameBoyInstruction.PerformSUB8Operation(mCPU, 0x91);
            instruction.PerformOperation(mCPU, mMemory);
            Assert.AreEqual(0x28, mCPU.ReadRegister8(GBCPURegister.A), "0x19 sub 0x91");
            Assert.IsTrue(mCPU.CFlag, "0x91 0x92 CFlag");
        }

        [TestMethod]
        public void TestDEC8()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0xF);
            GameBoyInstruction.PerformDEC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0xE, mCPU.ReadRegister8(GBCPURegister.A), "0xF");
            Assert.IsTrue(mCPU.NFlag, "0xF NFlag");
            Assert.IsFalse(mCPU.ZFlag, "0xF ZFlag");
            Assert.IsFalse(mCPU.HFlag, "0xF HFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0x0);
            GameBoyInstruction.PerformDEC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0xFF, mCPU.ReadRegister8(GBCPURegister.A), "0x0");
            Assert.IsTrue(mCPU.NFlag, "0x0 NFlag");
            Assert.IsFalse(mCPU.ZFlag, "0x0 ZFlag");
            Assert.IsTrue(mCPU.HFlag, "0x0 HFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0x1);
            GameBoyInstruction.PerformDEC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0x0, mCPU.ReadRegister8(GBCPURegister.A), "0x1");
            Assert.IsTrue(mCPU.NFlag, "0x1 NFlag");
            Assert.IsTrue(mCPU.ZFlag, "0x1 ZFlag");
            Assert.IsFalse(mCPU.HFlag, "0x1 HFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            GameBoyInstruction.PerformDEC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0xEF, mCPU.ReadRegister8(GBCPURegister.A), "0xF0");
            Assert.IsTrue(mCPU.NFlag, "0xF0 NFlag");
            Assert.IsFalse(mCPU.ZFlag, "0xF0 ZFlag");
            Assert.IsTrue(mCPU.HFlag, "0xF0 HFlag");
        }

        [TestMethod]
        public void TestDEC16()
        {
            mCPU.HLRegister = 0x0000;
            GameBoyInstruction.PerformDEC16Operation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0xFFFF, mCPU.HLRegister, "0x0000");

            mCPU.HLRegister = 0xFF00;
            GameBoyInstruction.PerformDEC16Operation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0xFEFF, mCPU.HLRegister, "0xFF00");
        }

        [TestMethod]
        public void TestINC8()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0xFF);
            GameBoyInstruction.PerformINC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0x00, mCPU.ReadRegister8(GBCPURegister.A), "0xFF");
            Assert.IsFalse(mCPU.NFlag, "0xFF NFlag");
            Assert.IsTrue(mCPU.ZFlag, "0xFF ZFlag");
            Assert.IsTrue(mCPU.HFlag, "0xFF HFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF);
            GameBoyInstruction.PerformINC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0x10, mCPU.ReadRegister8(GBCPURegister.A), "0xF");
            Assert.IsFalse(mCPU.NFlag, "0xF NFlag");
            Assert.IsFalse(mCPU.ZFlag, "0xF ZFlag");
            Assert.IsTrue(mCPU.HFlag, "0xF HFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            GameBoyInstruction.PerformINC8Operation(mCPU, GBCPURegister.A);
            Assert.AreEqual(0xF1, mCPU.ReadRegister8(GBCPURegister.A), "0xF0");
            Assert.IsFalse(mCPU.NFlag, "0xF0 NFlag");
            Assert.IsFalse(mCPU.ZFlag, "0xF0 ZFlag");
            Assert.IsFalse(mCPU.HFlag, "0xF0 HFlag");
        }

        [TestMethod]
        public void TestINC16()
        {
            mCPU.HLRegister = 0xFFFF;
            GameBoyInstruction.PerformINC16Operation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0, mCPU.HLRegister, "0xFFFF");

            mCPU.HLRegister = 0xFF00;
            GameBoyInstruction.PerformINC16Operation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0xFF01, mCPU.HLRegister, "0xFF00");

            mCPU.HLRegister = 0;
            GameBoyInstruction.PerformINC16Operation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(1, mCPU.HLRegister, "0");
        }

        [TestMethod]
        public void TestJP()
        {
            GameBoyInstruction.PerformJPOperation(mCPU, true, 0xFF00);
            Assert.AreEqual(0xFF00, mCPU.ProgramCounter, "0xFF00");

            GameBoyInstruction.PerformJPOperation(mCPU, true, 0);
            Assert.AreEqual(0, mCPU.ProgramCounter, "0");

            GameBoyInstruction.PerformJPOperation(mCPU, true, 0xFFFF);
            Assert.AreEqual(0xFFFF, mCPU.ProgramCounter, "0xFFFF");
        }

        [TestMethod]
        public void TestJR()
        {
            mCPU.ProgramCounter = 0x100;
            GameBoyInstruction.PerformJROperation(mCPU, true, 0x80);
            Assert.AreEqual(0xFF, mCPU.ProgramCounter, "0x100 0x81");

            mCPU.ProgramCounter = 0x100;
            GameBoyInstruction.PerformJROperation(mCPU, true, 0x80);
            Assert.AreEqual(0x100, mCPU.ProgramCounter, "0x100 0x80");

            mCPU.ProgramCounter = 0x100;
            GameBoyInstruction.PerformJROperation(mCPU, true, 0xF);
            Assert.AreEqual(0x10F, mCPU.ProgramCounter, "0x100 0xF");
        }

        [TestMethod]
        public void TestLD2Memory16()
        {
            GameBoyInstruction.PerformLD2Memory16Operation(mCPU, mMemory, 0xFF, 0xFF);
            Assert.AreEqual(0xFF, mMemory.Read8(0xFF), "0xFF 0xFF");
            Assert.AreEqual(0, mMemory.Read8(0x100), "0xFF 0xFF");

            GameBoyInstruction.PerformLD2Memory16Operation(mCPU, mMemory, 0xFF00, 0xFF);
            Assert.AreEqual(0xFF, mMemory.Read8(0xFF00), "0xFF00 0xFF");
            Assert.AreEqual(0, mMemory.Read8(0xFF01), "0xFF00 0xFF");

            GameBoyInstruction.PerformLD2Memory16Operation(mCPU, mMemory, 0xFF, 0xFF00);
            Assert.AreEqual(0, mMemory.Read8(0xFF), "0xFF 0xFF00");
            Assert.AreEqual(0xFF, mMemory.Read8(0x100), "0xFF 0xFF00");
        }

        [TestMethod]
        public void TestLD2Memory8()
        {
            GameBoyInstruction.PerformLD2Memory8Operation(mCPU, mMemory, 0xFF, 0xFF);
            Assert.AreEqual(0xFF, mMemory.Read8(0xFF), "0xFF 0xFF");

            GameBoyInstruction.PerformLD2Memory8Operation(mCPU, mMemory, 0xFF, 0x1F);
            Assert.AreEqual(0x1F, mMemory.Read8(0xFF), "0xFF 0x1F");
        }

        [TestMethod]
        public void TestLD2Reg16()
        {
            GameBoyInstruction.PerformLD2Reg16Operation(mCPU, 0xFF00, GBCPURegister.B, GBCPURegister.C);
            Assert.AreEqual(0xFF00,mCPU.ReadRegister16(GBCPURegister.B,GBCPURegister.C),"0xFF00");

            GameBoyInstruction.PerformLD2Reg16Operation(mCPU, 0, GBCPURegister.B, GBCPURegister.C);
            Assert.AreEqual(0, mCPU.ReadRegister16(GBCPURegister.B, GBCPURegister.C), "0");

            GameBoyInstruction.PerformLD2Reg16Operation(mCPU, 0xFF0, GBCPURegister.B, GBCPURegister.C);
            Assert.AreEqual(0xFF0, mCPU.ReadRegister16(GBCPURegister.B, GBCPURegister.C), "0xFF0");
        }

        [TestMethod]
        public void TestLD2Reg8()
        {
            GameBoyInstruction.PerformLD2Rg8Operation(mCPU, GBCPURegister.B, 0xFF);
            Assert.AreEqual(0xFF, mCPU.ReadRegister8(GBCPURegister.B), "0xFF");

            GameBoyInstruction.PerformLD2Rg8Operation(mCPU, GBCPURegister.B, 0);
            Assert.AreEqual(0, mCPU.ReadRegister8(GBCPURegister.B), "0");
        }

        [TestMethod]
        public void TestOR()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            GameBoyInstruction.PerformOROperation(mCPU, 0xF);
            Assert.AreEqual(0xFF, mCPU.ReadRegister8(GBCPURegister.A), "0xF0 0xF");
            Assert.IsFalse(mCPU.ZFlag, "0xF0 0xF ZFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0x0);
            GameBoyInstruction.PerformOROperation(mCPU, 0x0);
            Assert.AreEqual(0x0, mCPU.ReadRegister8(GBCPURegister.A), "0x0 0");
            Assert.IsTrue(mCPU.ZFlag, "0xF 0 ZFlag");

            mCPU.WriteRegister8(GBCPURegister.A, 0);
            GameBoyInstruction.PerformOROperation(mCPU, 0x11);
            Assert.AreEqual(0x11, mCPU.ReadRegister8(GBCPURegister.A), "0 0x11");
            Assert.IsFalse(mCPU.ZFlag, "0 0x11 ZFlag");

        }

        [TestMethod]
        public void TestPOP()
        {
            mMemory.Write8(0xF0, 0xF);
            mMemory.Write8(0xF1, 0xF);
            mCPU.StackPointer=0xF0;
            GameBoyInstruction.PerformPOPOperation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0xF0F, mCPU.HLRegister, "0xF 0xF");

            mMemory.Write8(0xF0, 0x0);
            mMemory.Write8(0xF1, 0xF);
            mCPU.StackPointer = 0xF0;
            GameBoyInstruction.PerformPOPOperation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0xF00, mCPU.HLRegister, "0x0 0xF");

            mMemory.Write8(0xF0, 0xFF);
            mMemory.Write8(0xF1, 0x0);
            mCPU.StackPointer = 0xF0;
            GameBoyInstruction.PerformPOPOperation(mCPU, GBCPURegister.H, GBCPURegister.L);
            Assert.AreEqual(0xFF, mCPU.HLRegister, "0xFF 0x0");
        }

        [TestMethod]
        public void TestPush()
        {
            mCPU.StackPointer = 0x0;
            //0xff10
            mCPU.WriteRegister8(GBCPURegister.B,0xff);
            mCPU.WriteRegister8(GBCPURegister.C,0x10);
            GameBoyInstruction.PerformPUSHOperation(mCPU, GBCPURegister.B, GBCPURegister.C);
            Assert.AreEqual(0x10, mCPU.PopStack());
            Assert.AreEqual(0xff, mCPU.PopStack());
        }

        [TestMethod]
        public void TestRESMem()
        {
            mMemory.Write8(0xF0, 0x1);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 0, 0xF0);
            Assert.AreEqual(0x0, mMemory.Read8(0xF0), "0xF0 0x1 1");

            mMemory.Write8(0xF0, 0x1);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 1, 0xF0);
            Assert.AreEqual(0x1, mMemory.Read8(0xF0), "0xF0 0x1 2");

            mMemory.Write8(0xF0, 0x10);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 2, 0xF0);
            Assert.AreEqual(0x10, mMemory.Read8(0xF0), "0xF0 0x10 3");

            mMemory.Write8(0xF0, 0x10);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 3, 0xF0);
            Assert.AreEqual(0x10, mMemory.Read8(0xF0), "0xF0 0x10 4");

            mMemory.Write8(0xF0, 0x10);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 4, 0xF0);
            Assert.AreEqual(0x0, mMemory.Read8(0xF0), "0xF0 0x10 5");

            mMemory.Write8(0xF0, 0x10);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 5, 0xF0);
            Assert.AreEqual(0x10, mMemory.Read8(0xF0), "0xF0 0x10 6");

            mMemory.Write8(0xF0, 0x10);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 6, 0xF0);
            Assert.AreEqual(0x10, mMemory.Read8(0xF0), "0xF0 0x10 7");

            mMemory.Write8(0xF0, 0x10);
            GameBoyInstruction.PerformRESMemOperation(mMemory, 7, 0xF0);
            Assert.AreEqual(0x10, mMemory.Read8(0xF0), "0xF0 0x10 8");

        }

        [TestMethod]
        public void TestRESReg()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0x1);
            GameBoyInstruction.PerformRESRegOperation(mCPU, 0, GBCPURegister.A);
            Assert.AreEqual(0, mCPU.ReadRegister8(GBCPURegister.A), "0x1 1");

            mCPU.WriteRegister8(GBCPURegister.A, 0x1);
            GameBoyInstruction.PerformRESRegOperation(mCPU, 1, GBCPURegister.A);
            Assert.AreEqual(1, mCPU.ReadRegister8(GBCPURegister.A), "0x1 2");
        }

        [TestMethod]
        public void TestRST()
        {
            GameBoyInstruction.PerformRSTOperation(mCPU, 0x00);
            Assert.AreEqual(0, mCPU.ProgramCounter, "0x00");
        }

        [TestMethod]
        public void TestXOR()
        {
            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            GameBoyInstruction.PerformXOROperation(mCPU, 0xF0);
            Assert.AreEqual(0,mCPU.ReadRegister8(GBCPURegister.A),"0xF0 0xF0");
            Assert.IsTrue(mCPU.ZFlag, "0xF0 0xF0");

            mCPU.WriteRegister8(GBCPURegister.A, 0xF0);
            GameBoyInstruction.PerformXOROperation(mCPU, 0xF);
            Assert.AreEqual(0xFF, mCPU.ReadRegister8(GBCPURegister.A), "0xF0 0xF");
            Assert.IsFalse(mCPU.ZFlag, "0xF0 0xF");
        }
    }
}
